package com.tang.framework.component.fliter;

import com.alibaba.fastjson2.JSON;
import com.tang.common.constant.message.LocaleMessage;
import com.tang.common.utils.ServletUtil;
import com.tang.framework.component.TokenService;
import com.tang.framework.core.domain.HttpResult;
import com.tang.framework.core.model.LoginUser;
import com.tang.common.exception.BusinessException;
import lombok.SneakyThrows;

import org.jetbrains.annotations.NotNull;
import org.springframework.context.MessageSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.util.Objects;

import static com.tang.common.constant.Constant.TOKEN_HEADER;


@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {


    @Resource
    private AuthenticationConfiguration authenticationConfiguration;


    @Resource
    private TokenService tokenService;

    @Resource
    private MessageSource messageSource;


    @SneakyThrows
    @Override
    protected void doFilterInternal(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (Objects.nonNull(loginUser) && Objects.isNull(SecurityContextHolder.getContext().getAuthentication())) {
            String loginPassword = loginUser.getLoginPassword();
            AuthenticationManager authenticationManager = authenticationConfiguration.getAuthenticationManager();
            try {
                Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginUser.getUsername(), loginUser.getLoginPassword()));
                SecurityContextHolder.getContext().setAuthentication(authenticate);
                loginUser = (LoginUser) authenticate.getPrincipal();
                loginUser.setLoginPassword(loginPassword);
                loginUser.setToken(request.getHeader(TOKEN_HEADER));
                tokenService.refresh(loginUser);
            } catch (Exception e) {
                e.printStackTrace();
                if (e.getCause() instanceof BusinessException) {
                    ServletUtil.renderString(response, JSON.toJSONString(HttpResult.error(((BusinessException) e.getCause()).getErrorCodeMessage())));
                    return;
                }
                if (e instanceof BadCredentialsException) {
                    ServletUtil.renderString(response, JSON.toJSONString(HttpResult.error(messageSource.getMessage(LocaleMessage.Account.PASSWORD_HAS_MODIFY, null, request.getLocale()))));
                    return;
                }
                if (e instanceof LockedException) {
                    ServletUtil.renderString(response, JSON.toJSONString(HttpResult.error(messageSource.getMessage(LocaleMessage.Account.USER_LOCK, null, request.getLocale()))));
                    return;
                }
                ServletUtil.renderString(response, JSON.toJSONString(HttpResult.error(messageSource.getMessage(LocaleMessage.Account.PERMISSION_ERROR, null, request.getLocale()))));
                return;
            }
        }
        filterChain.doFilter(request, response);
    }
}
